#pragma once
/*
 * Copyright © 2008 University of Houston
 * All rights reserved
 */

#include <stdio.h>
#include "session.h"

using namespace std;

class session;
class timedHeader;
class algorithm;
class filter;
class sessionAnalyzer;

#define ALG_DO_ANALYSIS		0	// Algorithm should do update and analysis
#define ALG_DO_UPDATE		1	// Algorithm should do update only
#define ALG_DO_NOTHING		2	// Algorithm should do neither update or analysis

class filter
{
public:
	filter() {};
	virtual ~filter() {};

	/*
	 * Implemented by subclasses to set any initial values needed by
	 * the filter.
	 */
	virtual void initializeVars() {};

	/*
	 * Decides whether the given packet should be passed the algorithm for
	 * analysis or not.
	 * @param th The given packet
	 * @return 	ALG_DO_ANALYSIS 	If alg should preform analysis and update
	 * 			ALG_DO_UPDATE 		If alg should update without analysis
	 * 			ALG_DO_NOTHING 		If no update and no analysis
	 */
	virtual int update(timedHeader *th);

	/*
	 * Returns a new-allocated filter object, corresponding to filterID.
	 * @return filter The requested filter object
	 */
	static filter* 	getFilter(int filterID);

	/*
	 * Returns a string with the name of the filter
	 * given the filter id number.
	 */
	static string	getFilterName(int filterID);
	
	/*
	 * Returns the name of the current filter object.
	 */
	virtual string	getName() { return "Default Filter"; };
};


/*
 * NearestHopFilter only accepts packets which are results of direct and
 * automatic responses to the nearest hop machine. No user delay is
 * present.
 */
class nearestHopFilter : public filter
{
public:
	void initializeVars();
	int update(timedHeader *th);
	long double getRtt() { return estimatedRtt; };
	virtual string	getName() { return "Nearest Hop Filter"; };

private:
	tcp_seq 	last_th_seq;	//th_seq of prev packet
	tcp_seq 	last_th_ack;	//th_ack of prev packet
	bool 		ready;

	long double	estimatedRtt;
	long double	count;
	long double totalTime;
	long double sensitivity;
	long double lastPktTime;
};


/*
 * UserDelayFilter denies all automatically timed acknowledgement packets and
 * only accpets those packets subject to user delay.
 */
class userDelayFilter : public filter
{
public:
	void initializeVars(); int update(timedHeader *th);
	virtual string	getName() { return "User Delay Filter"; };

private:
	tcp_seq last_th_seq;			//th_seq of prev packet
	tcp_seq last_th_ack;			//th_ack of prev packet
};


/*
 * Accepts all incoming encrypted push packets
 */
class encryptedInFilter : public filter
{
public:
	int update(timedHeader *th);
	virtual string	getName() { return "Incoming-only filter"; };
};


/*
 * Accepts all outgoing encrypted push packets
 */
class encryptedOutFilter : public filter
{
public:
	int update(timedHeader *th);
	virtual string	getName() { return "Outgoing-only filter"; };
};


/*
 * Accepts the first packet of each new command entered by the user.
 *
 * This is not a perfect filter.. Typing quickly will often be recognized
 * as a new command. You can adjust the sensitivty. Higher sensitivity will
 * recognize more commands such as 'cd' or simply enter, but will also
 * fall for quick typing. Lower sensitivity will only recognize commands
 * such as 'clear' or 'ls' but will not be sensitive to quick typing.
 */
class commandFilter :  public filter
{
public:
	void initializeVars();
	int update(timedHeader *th);
	virtual string	getName() { return "Command Filter"; };

private:
	int 		pktsSinceChar;	// Num packets since last character
	int			charCount;		// Characters typed in this command
	int			sensitivity;	// See above description

	tcp_seq last_th_seq;		//th_seq of prev packet
	tcp_seq last_th_ack;		//th_ack of prev packet
};

/*
 * Attempts to model reply echo time by finding the time difference
 * between the latest outgoing ecrypted packet and the next incoming
 * encrypted one.
 */
class naiveEchoFilter : public filter
{
public:
	void initializeVars();
	int update(timedHeader *th);
	virtual string	getName() { return "Naive Echo Filter"; };

private:
	bool		ready; 			// Only true after we see outgoing enc
};

/*
 * Attempts to only identify packet streams
 */
class streamFilter : public filter
{
public:
	void initializeVars();
	int update(timedHeader *th);
	virtual string	getName() { return "Stream Filter"; };

private:
	tcp_seq last_th_seq;		//th_seq of prev packet
	tcp_seq last_th_ack;		//th_ack of prev packet
};


